package com.zjdiepu.www.security.client.encode;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zjdiepu.www.config.ClientConfig;
import com.zjdiepu.www.request.BaseRequest;
import com.zjdiepu.www.security.base.enums.ResultCode;
import com.zjdiepu.www.security.client.sign.ClientSignFactory;
import com.zjdiepu.www.security.exception.BasePartnerException;
import com.zjdiepu.www.security.server.core.Partners;
import com.zjdiepu.www.security.sign.ICertificatelSignature;
import com.zjdiepu.www.security.sign.ISign;
import com.zjdiepu.www.security.sign.rsa.RsaProvider;
import com.zjdiepu.www.security.sign.rsa.RsaSign;

/**
 * 类描述:基础实现 <br/>     
 * 项目名称:zjdiepu-client <br/> 
 * 类名称:BasePartnerService <br/>     
 * 创建人:xiongxiaotun <br/> 
 * 创建时间:2017年8月16日 上午11:47:58  <br/>   
 * 修改人:xiongxiaotun <br/> 
 * 修改时间: 2017年8月16日 上午11:47:58   <br/>  
 * 修改备注:   <br/> 
 * @version V1.0   <br/>
 */
public abstract class BaseEncryptService {
	private static final Logger logger = LoggerFactory.getLogger(BaseEncryptService.class);
	
	/**
	 * 签名并加密
	 * @author xiongxiaotun <br/>
	 * @Title sign  <br/>
	 * @Description 签名并加密 <br/>
	 * @param certificatelSignature 待签名并加密对象
	 * @param partner 合作伙伴
	 * @version V1.0  <br/>
	 * @throws BasePartnerException 
	 */
	public String signEncrypt(BaseRequest baseRequest, Partners partner) throws BasePartnerException{
		if(null == baseRequest) {
			return null;
		}
		boolean signSwitch = ClientConfig.getPartnerSignSwitch(partner);
		if(signSwitch) {
			ISign sign = ClientSignFactory.getSign(partner);
			String signSecretKey = ClientConfig.getPartnerSignSecretKey(partner);
			String signSaltOrSecretKey = ClientSignFactory.getSignSecretKey(partner);
			String signName = ClientConfig.getPartnerSignName(partner);
			String signCovenantKeyName = ClientConfig.getPartnerSignCovenantKeyName(partner);
			baseRequest.setTimestamp(System.currentTimeMillis());
			String generateSign = sign.generateSign(baseRequest, signSecretKey, signSaltOrSecretKey, signName, signCovenantKeyName, false);
			if(StringUtils.isBlank(generateSign)) {
				throw new BasePartnerException(ResultCode.FAIL_SIGN);
			}
			baseRequest.setSign(generateSign);
		}
		String encrypt = ClientEncryptAndDencryptUtil.encrypt(JSON.toJSONString(baseRequest), partner);
		if(StringUtils.isEmpty(encrypt)) {
			throw new BasePartnerException(ResultCode.FAIL_ENCODE_VALIDATE);
		}
		return encrypt;
	}
	
	/**
	 * @author xiongxiaotun <br/>
	 * @Title parseObject  <br/>
	 * @Description 解密、验签，并解析结果 <br/>
	 * @param responseJsonStr
	 * @param partner 合作伙伴
	 * @return
	 * @version V1.0 <br/>
	 * @throws BasePartnerException 
	 */
	public <T extends ICertificatelSignature> T valdateDencrypt(String responseStr, Class<T> clazz, Partners partner) throws BasePartnerException {
		if(StringUtils.isBlank(responseStr)) {
			throw new BasePartnerException(ResultCode.FAIL_HTTP);
		}
		boolean encodeResponseSwitch = ClientConfig.getPartnerEncodeResponseSwitch(partner);
		if(encodeResponseSwitch) {
			responseStr = ClientEncryptAndDencryptUtil.dencrypt(responseStr, partner);
			if(StringUtils.isBlank(responseStr)) {
				throw new BasePartnerException(ResultCode.FAIL_DENCODE_VALIDATE);
			}
		}
		JSONObject jsonObject = JSONObject.parseObject(responseStr);
		Integer resultCode = jsonObject.getInteger("resultCode");
		String resultMsg = jsonObject.getString("resultMsg");
		if(ResultCode.SUCCESS.getCode().equals(resultCode)) {
			JSONObject contentJsonObject = jsonObject.getJSONObject("content");
			if(null == contentJsonObject) {
				return null;
			}
			T ret = contentJsonObject.toJavaObject(clazz);
			if(null != ret) {
				boolean signResponseSwitch = ClientConfig.getPartnerSignResponseSwitch(partner);
				if(signResponseSwitch) {
					ISign sign = ClientSignFactory.getSign(partner);
					String signSecretKey = ClientConfig.getPartnerSignSecretKey(partner);
					String signSaltOrSecretKey = ClientSignFactory.getSignSecretKey(partner);
					String signName = ClientConfig.getPartnerSignName(partner);
					String signCovenantKeyName = ClientConfig.getPartnerSignCovenantKeyName(partner);
					String targetSign = ret.getSign();
					if(sign instanceof RsaSign) {
						targetSign = RsaProvider.deSignWithPub(targetSign, partner);
					}
					if(!sign.verifySign(ret, targetSign, signSecretKey, signSaltOrSecretKey, signName, signCovenantKeyName)){
						logger.debug("解密、验签，并解析结果:验签失败.response:{}.", contentJsonObject.toJSONString());
						throw new BasePartnerException(ResultCode.FAIL_SIGN_VALIDATE);
					}
				}
			}
			return ret;
		} else {
			logger.debug("解密、验签，并解析结果:resultCode:{}, resultMsg:{}.", resultCode, resultMsg);
			throw new BasePartnerException(resultCode, resultMsg);
		}
	}
}
